import RequestHelper from "./RequestHelper"
import TimeUtils from "@/utils/TimeUtils"
import RestClient from "./RestClient"
import StringUtils from "@/utils/StringUtils"

const TencentRequest = {
    /**
     * host map.
     */
    _hostMap: {
        cvm: 'cvm.tencentcloudapi.com',
        vpc: 'vpc.tencentcloudapi.com',
        ssl: 'ssl.tencentcloudapi.com'
    },
    REGION_MAP : {
        'ap-bangkok': {
            code: 'ap-bangkok',
            name: '亚太东南（曼谷）'
        },
        'ap-beijing': {
            code: 'ap-beijing',
            name: '华北地区（北京）'
        },
        'ap-chengdu': {
            code: 'ap-chengdu',
            name: '西南地区（成都）'
        },
        'ap-chongqing': {
            code: 'ap-chongqing',
            name: '西南地区（重庆）'
        },
        'ap-guangzhou': {
            code: 'ap-guangzhou',
            name: '华南地区（广州）'
        },
        'ap-hongkong': {
            code: 'ap-hongkong',
            name: '港澳台地区（中国香港）'
        },
        'ap-jakarta': {
            code: 'ap-jakarta',
            name: '亚太东南（雅加达）'
        },
        'ap-mumbai': {
            code: 'ap-mumbai',
            name: '亚太南部（孟买）'
        },
        'ap-nanjing': {
            code: 'ap-nanjing',
            name: '华东地区（南京）'
        },
        'ap-seoul': {
            code: 'ap-seoul',
            name: '亚太东北（首尔）'
        },
        'ap-shanghai': {
            code: 'ap-shanghai',
            name: '华东地区（上海）'
        },
        'ap-shanghai-fsi': {
            code: 'ap-shanghai-fsi',
            name: '华东地区（上海金融）'
        },
        'ap-shenzhen-fsi': {
            code: 'ap-shenzhen-fsi',
            name: '华南地区（深圳金融）'
        },
        'ap-singapore': {
            code: 'ap-singapore',
            name: '亚太东南（新加坡）'
        },
        'ap-tokyo': {
            code: 'ap-tokyo',
            name: '亚太东北（东京）'
        },
        'eu-frankfurt': {
            code: 'eu-frankfurt',
            name: '欧洲地区（法兰克福）'
        },
        'na-ashburn': {
            code: 'na-ashburn',
            name: '美国东部（弗吉尼亚）'
        },
        'na-siliconvalley': {
            code: 'na-siliconvalley',
            name: '美国西部（硅谷）'
        },
        'na-toronto': {
            code: 'na-toronto',
            name: '北美地区（多伦多）'
        },
        'sa-saopaulo': {
            code: 'sa-saopaulo',
            name: '南美地区（圣保罗）'
        }
    },
    /**
     * 创建 Authorization.
     * @param account
     * @param service
     * @param method
     * @param headers
     * @param query
     * @param bodyString
     * @param timestamp
     * @return {string}
     * @private
     */
    _buildToken(account, service, method, headers, query, bodyString, timestamp) {
        // step1: 拼接规范请求串
        let canonicalQueryString = '';
        if (query) {
            if (typeof query === 'string') {
                canonicalQueryString = query
            } else {
                canonicalQueryString = Object.keys(query).map(key => {
                    let value = query[key] ? encodeURIComponent(query[key]) : ''
                    return `${key}=${value}`
                }).sort().join('&')
            }
        }

        let canonicalHeaders = Object.keys(headers).map(key=> {
            let value = headers[key] ? headers[key] : ''
            value = value.toString().toLowerCase()
            key = key.toLowerCase()
            return `${key}:${value}\n`
        }).sort().join('')

        let signedHeaders = Object.keys(headers).map(key=> {return key.toLowerCase()}).sort().join(';')
        let hashedRequestPayload = RequestHelper.sha256(bodyString).toLowerCase()

        let canonicalRequest = `${method}\n/\n${canonicalQueryString}\n${canonicalHeaders}\n${signedHeaders}\n${hashedRequestPayload}`
        console.log('tencent CanonicalRequest: ', canonicalRequest)

        // step2: 拼接待签名字符串
        let requestTimestamp = timestamp
        let date = new Date()
        let dateStr = TimeUtils.formatDate(date, 'yyyy-MM-dd')
        let credentialScope = `${dateStr}/${service}/tc3_request`
        let hashedCanonicalRequest = RequestHelper.sha256(canonicalRequest).toLowerCase()
        let stringToSign = 'TC3-HMAC-SHA256' + "\n" + requestTimestamp + "\n" + credentialScope + "\n" + hashedCanonicalRequest
        console.log('tencent StringToSign: ', stringToSign)

        // stp3: 计算签名
        // step3.1: 计算派生签名密钥
        let sk = 'TC3' + account.access_key;
        console.log('tencent first key:', sk)
        let secretDate = RequestHelper.hmcShA256Def(dateStr, sk)
        console.log('tencent date key:', secretDate)
        let secretService = RequestHelper.hmcShA256Def(service, secretDate)
        console.log('tencent service key:', secretService)
        let secretSigning = RequestHelper.hmcShA256Def('tc3_request', secretService)


        // step3.2: 计算签名
        let signature = RequestHelper.hmcShA256(stringToSign, secretSigning).toLowerCase()

        console.log('tencent signature: ', signature)

        let accountId = account.access_id

        return `TC3-HMAC-SHA256 Credential=${accountId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`
    },

    /**
     * 请求.
     * @param region
     * @param account
     * @param service
     * @param action
     * @param body
     * @param callback
     * @param failCallback
     * @param headers
     * @param timeout
     */
    request(region, account, service, action, body, callback, failCallback, headers, timeout) {
        headers = headers || {}
        headers['Host'] = this._hostMap[service]
        headers['Content-Type'] = 'application/json'
        headers['X-TC-Action'] = action

        let bodyString = '{}';
        if (body) {
            if (typeof body === 'string') {
                bodyString = body
            } else {
                bodyString = StringUtils.isBlank(body) ? '{}' : JSON.stringify(body)
            }
        }

        let method = 'POST'

        let timestamp = TimeUtils.currentTimestampSecond();
        headers['Authorization'] = this._buildToken(account, service, method, headers, null, bodyString, timestamp)
        headers['X-TC-Timestamp'] = timestamp
        headers['X-TC-Version'] = '2017-03-12'
        if (service === 'ssl') {
            headers['X-TC-Version'] = '2019-12-05'
        }
        if (service !== 'ssl') {
            headers['X-TC-Region'] = region
        }

        RestClient.https(headers['Host'], 443, '/', method, headers, bodyString, (response) => {
            if (response.Response.Error) {
                if (failCallback) {
                    failCallback(response.Response.Error)
                } else {
                    console.error(action, response)
                }
                return
            }
            if (callback) {
                callback(response.Response)
            } else {
                console.debug(action, 'use default callback: ', response)
            }
        }, failCallback, timeout)
    }
}

export default TencentRequest
